home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / x / animutil / xanim229.lha / xanim / xanim_gif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-08  |  14.2 KB  |  617 lines

  1.  
  2. /*
  3.  * xanim_gif.c
  4.  *
  5.  * Copyright (C) 1990,1991,1992 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed
  9.  * without fee provided that this copyright notice is preserved 
  10.  * intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include "mytypes.h"
  21. #include "xanim.h"
  22. #include "xanim_gif.h"
  23.  
  24. void GIF_Read_File();
  25. void GIF_Decompress();
  26. void GIF_Get_Next_Entry();
  27. void GIF_Add_To_Table();
  28. void GIF_Send_Data();
  29. void GIF_Init_Table();
  30. void GIF_Clear_Table();
  31. ULONG GIF_Get_Code();
  32. void GIF_Screen_Header();
  33. void GIF_Image_Header();
  34. LONG GIF_Get_Short();
  35. LONG Is_GIF_File();
  36.  
  37. #define MAXVAL  4100            /* maxval of lzw coding size */
  38. #define MAXVALP 4200
  39.  
  40. ULONG GIF_Get_Code();
  41. ULONG GIF_Get_Bits();
  42. ULONG GIF_Get_Word();
  43.  
  44. #define GIF_CMAP_SIZE 256
  45. static GIF_Screen_Hdr gifscrn;
  46. static GIF_Image_Hdr gifimage;
  47. static GIF_Color gifcolor[GIF_CMAP_SIZE];
  48. static GIF_Table table[MAXVALP];
  49.  
  50. static ULONG root_code_size,code_size,CLEAR,EOI,INCSIZE;
  51. static ULONG nextab;
  52. static ULONG gif_mask[16] = {1,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,0,0};
  53. static ULONG gif_ptwo[16] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,0,0};
  54. static UBYTE gif_buff[MAXVALP];
  55. static ULONG gif_block_size;
  56. static LONG bits,num_bits;
  57. static lace_flag;
  58.  
  59. static LONG pic_i,pic_size;
  60.  
  61. /*
  62.  *
  63.  */
  64. void GIF_Read_File(fname,first_image)
  65. char *fname;
  66. LONG first_image;
  67. {
  68.  FILE *fp;
  69.  LONG i,exit_flag;
  70.  ACTION *act;
  71.  
  72.  if ( (fp=fopen(fname,"r"))==0)
  73.  { 
  74.   fprintf(stderr,"Can't open %s for reading.\n",fname); 
  75.   TheEnd();
  76.  }
  77.  
  78.  GIF_Screen_Header(fp,&first_image);
  79.  
  80.  /*** read until  ,  separator */
  81.  do
  82.  {
  83.   i=fgetc(fp);
  84.   if ( (i<0) && feof(fp))
  85.   {
  86.    fclose(fp);
  87.    TheEnd1("GIF_Read_Header: Unexpected End of File\n");
  88.   }
  89.  } while(i != ',');
  90.  
  91.  exit_flag = 0;
  92.  while(!exit_flag)
  93.  {
  94.   ACT_REGION_HDR *act_reg_hdr;
  95.   
  96.   /* Read Image Header
  97.    */
  98.   GIF_Image_Header(fp,&first_image);
  99.  
  100.   /*** Setup ACTION for REGION */
  101.   act = &action[action_cnt];
  102.   action_cnt++;
  103.   act->type = ACT_REGION;
  104.   if (jiffy_flag) act->time = jiffy_flag;
  105.   else act->time = MS_PER_60HZ;
  106.   pic_size = imagex * imagey;
  107.   act_reg_hdr = (ACT_REGION_HDR *) 
  108.     malloc(sizeof(ACT_REGION_HDR) + pic_size * x11_bytes_pixel);
  109.  
  110.   act_reg_hdr->xpos  = gifimage.left; 
  111.   act_reg_hdr->ypos  = gifimage.top; 
  112.   act_reg_hdr->xsize = gifimage.width; 
  113.   act_reg_hdr->ysize = gifimage.height; 
  114.   act->data = (char *) act_reg_hdr;
  115.  
  116.   pic_i=0;
  117.   GIF_Decompress(fp,act_reg_hdr->data,(x11_cmap_size - imagec));
  118.  
  119.  /*** read until "," ";" or feof */
  120.   do
  121.   {
  122.    i=fgetc(fp);
  123.    if ( (i<0) || (i == ';')) exit_flag = 1;
  124.   } while( (i != ',') && (!exit_flag) );
  125.  
  126.  } /*** end of while images */
  127.  
  128.  fclose(fp);
  129. }
  130.  
  131. void GIF_Decompress(fp,pic,gif_pix_offset)
  132. FILE *fp;
  133. char *pic;
  134. LONG gif_pix_offset;
  135. {
  136.  register ULONG code,old;
  137.  
  138.  bits = 0;
  139.  num_bits=0;
  140.  gif_block_size=0;
  141.      /* starting code size of LZW */
  142.  root_code_size=(fgetc(fp) & 0xff); 
  143. if (debug_flag) fprintf(stderr,"root code size = %ld\n",root_code_size);
  144.  GIF_Clear_Table();                /* clear decoding symbol table */
  145.  
  146.  code=GIF_Get_Code(fp);
  147.  
  148.  if (code==CLEAR) 
  149.  {
  150.   GIF_Clear_Table(); 
  151.   code=GIF_Get_Code(fp);
  152.  }
  153.  /* write code(or what it currently stands for) to file */
  154.  GIF_Send_Data(code,pic,gif_pix_offset);   
  155.  old=code;
  156.  code=GIF_Get_Code(fp);
  157.  do
  158.  {
  159.   if (table[code].valid==1)    /* if known code */
  160.   {
  161.        /* send it's associated string to file */
  162.     GIF_Send_Data(code,pic,gif_pix_offset);
  163.     GIF_Get_Next_Entry(fp);       /* get next table entry (nextab) */
  164.     GIF_Add_To_Table(old,code,nextab);  /* add old+code to table */
  165.     old=code;
  166.   }
  167.   else      /* code doesn't exist */
  168.   {
  169.     GIF_Add_To_Table(old,old,code);   /* add old+old to table */
  170.     GIF_Send_Data(code,pic,gif_pix_offset);
  171.     old=code;
  172.   }
  173.   code=GIF_Get_Code(fp);
  174.   if (code==CLEAR)
  175.   { 
  176.    GIF_Clear_Table();
  177.    code=GIF_Get_Code(fp);
  178.    GIF_Send_Data(code,pic,gif_pix_offset);
  179.    old=code;
  180.    code=GIF_Get_Code(fp);
  181.   }
  182.  } while(code!=EOI);
  183. }
  184.  
  185. void GIF_Get_Next_Entry(fp)
  186. FILE *fp;
  187. {
  188.    /* table walk to empty spot */
  189.  while(  (table[nextab].valid==1)
  190.        &&(nextab<MAXVAL)
  191.       ) nextab++;
  192.  /* 
  193.   * Ran out of space??!?  Something's roached 
  194.   */
  195.  if (nextab>=MAXVAL)    
  196.  { 
  197.   fprintf(stderr,"Error: GetNext nextab=%ld\n",nextab);
  198.   fclose(fp);
  199.   TheEnd();
  200.  }
  201.  if (nextab==INCSIZE)   /* go to next table size (and LZW code size ) */
  202.  {
  203.    /* fprintf(stderr,"GetNext INCSIZE was %ld ",nextab); */
  204.    code_size++; INCSIZE=(INCSIZE*2)+1;
  205.    if (code_size>=12) code_size=12;
  206. /*   fprintf(stderr,"<%ld>",INCSIZE); */
  207.  }
  208.  
  209. }
  210. /*  body is associated string
  211.     next is code to add to that string to form associated string for
  212.     index
  213. */     
  214.  
  215. void GIF_Add_To_Table(body,next,index)
  216. register ULONG body,next,index;
  217. {
  218.  if (index>MAXVAL)
  219.  { 
  220.   fprintf(stderr,"Error index=%ld\n",index);
  221.  }
  222.  else
  223.  {
  224.   table[index].valid=1;
  225.   table[index].data=table[next].first;
  226.   table[index].first=table[body].first;
  227.   table[index].last=body;
  228.  }
  229. }
  230.  
  231. void GIF_Send_Data(index,pic,gif_pix_offset)
  232. register LONG index;
  233. char *pic;
  234. LONG gif_pix_offset;
  235. {
  236.  register LONG i,j;
  237.  i=0;
  238.  do         /* table walk to retrieve string associated with index */
  239.  { 
  240.   gif_buff[i]=table[index].data; 
  241.   i++;
  242.   index=table[index].last;
  243.   if (i>MAXVAL)
  244.   { 
  245.    fprintf(stderr,"Error: Sending i=%ld index=%ld\n",i,index);
  246.    TheEnd();
  247.   }
  248.  } while(index>=0);
  249.  
  250.  /* now invert that string since we retreived it backwards */
  251.  i--;
  252.  for(j=i;j>=0;j--)
  253.  {
  254.   if (x11_display_type == PSEUDO_COLOR_8BIT) 
  255.         pic[pic_i] = gif_buff[j] | gif_pix_offset;
  256.   else
  257.   {
  258.    if (x11_display_type == TRUE_COLOR_24BIT)
  259.    {
  260.     ((ULONG *)(pic))[pic_i] = gifcolor[ gif_buff[j] ].pixel;
  261.    }
  262.   }
  263.   pic_i++;
  264.  
  265.   if (lace_flag)
  266.   {
  267.    if ((pic_i % imagex) == 0 )
  268.    { 
  269.     switch(lace_flag)
  270.     {
  271.      case 1: pic_i += imagex * 7; break; /* fill every 8th row */
  272.      case 2: pic_i += imagex * 7; break; /* fill every 8th row */
  273.      case 3: pic_i += imagex * 3; break; /* fill every 4th row */
  274.      case 4: pic_i += imagex    ; break; /* fill every other row */
  275.     }
  276.    }
  277.    if (pic_i > pic_size)
  278.    {
  279.     lace_flag++;
  280.     switch(lace_flag)
  281.     {
  282.      case 2: pic_i = imagex << 2; break;  /* start at 4th row */
  283.      case 3: pic_i = imagex << 1; break;  /* start at 2nd row */
  284.      case 4: pic_i = imagex;      break;  /* start at 1st row */
  285.      default: fprintf(stderr,"unlacing error\n");
  286.               lace_flag = 0;
  287.               pic_i = 0;
  288.               break;
  289.     }
  290.    }
  291.   } /*** end of if lace_flag */
  292.  } /*** end of code expansion */
  293. }
  294.  
  295.  
  296. /* 
  297.  * initialize string table 
  298.  */
  299. void GIF_Init_Table()       
  300. {
  301.  register LONG maxi,i;
  302.  
  303. if (debug_flag) fprintf(stderr,"Initing Table...");
  304.  maxi=gif_ptwo[root_code_size];
  305.  for(i=0; i<maxi; i++)
  306.  {
  307.   table[i].data=i;   
  308.   table[i].first=i;
  309.   table[i].valid=1;  
  310.   table[i].last = -1;
  311.  }
  312.  CLEAR=maxi; 
  313.  EOI=maxi+1; 
  314.  nextab=maxi+2;
  315.  INCSIZE = (2*maxi)-1;
  316.  code_size=root_code_size+1;
  317. if (debug_flag) fprintf(stderr,"done\n");
  318. }
  319.  
  320.  
  321. /* 
  322.  * clear table 
  323.  */
  324. void GIF_Clear_Table()   
  325. {
  326.  register LONG i;
  327. if (debug_flag) fprintf(stderr,"Clearing Table...\n");
  328.  for(i=0;i<MAXVAL;i++) table[i].valid=0;
  329.  GIF_Init_Table();
  330. }
  331.  
  332.  
  333. /*CODE*/
  334. ULONG GIF_Get_Code(fp) /* get code depending of current LZW code size */
  335. FILE *fp;
  336. {
  337.  ULONG code;
  338.  register LONG tmp;
  339.  
  340.  while(num_bits < code_size)
  341.  {
  342.   /**** if at end of a block, start new block */
  343.   if (gif_block_size==0)
  344.   {
  345.    tmp = fgetc(fp);
  346.    if (tmp >= 0 ) gif_block_size=(ULONG)(tmp);
  347.    else TheEnd1("EOF in data stream\n");
  348.    if (debug_flag) fprintf(stderr,"New Block size=%ld\n",gif_block_size);
  349.   }
  350.  
  351.   tmp = fgetc(fp);   gif_block_size--;
  352.   if (tmp >= 0)
  353.   {
  354. /*POD added ULONG on 0xff */
  355.    bits |= ( ((ULONG)(tmp) & (ULONG)(0xff)) << num_bits );
  356. if (debug_flag) fprintf(stderr,"tmp=%lx bits=%lx num_bits=%ld\n",
  357.             tmp,bits,num_bits);
  358.  
  359.    num_bits+=8;
  360.   }
  361.   else TheEnd1("EOF in data stream\n");
  362.  }
  363.  
  364.  code = bits & gif_mask[code_size];
  365.  bits >>= code_size;  
  366.  num_bits -= code_size;
  367. if (debug_flag) fprintf(stderr,"code=%lx \n",code);
  368.  
  369.  
  370.  if (code>MAXVAL)
  371.  {
  372.   fprintf(stderr,"\nError! in stream=%lx \n",code);
  373.   fprintf(stderr,"CLEAR=%lx INCSIZE=%lx EOI=%lx code_size=%lx \n",
  374.                                            CLEAR,INCSIZE,EOI,code_size);
  375.   code=EOI;
  376.  }
  377.  
  378.  if (code==INCSIZE)
  379.  {
  380. if (debug_flag) fprintf(stderr,"code=INCSIZE(%ld)\n",INCSIZE);
  381.   if (code_size<12)
  382.   {
  383.    code_size++; INCSIZE=(INCSIZE*2)+1;
  384.   }
  385.   else if (debug_flag) fprintf(stderr,"<13?>");
  386. if (debug_flag) fprintf(stderr,"new size = %ld\n",code_size);
  387.  }
  388.  
  389.  return(code);
  390. }
  391.  
  392.  
  393. /* 
  394.  * read GIF header 
  395.  */
  396. void GIF_Screen_Header(fp,first_image)
  397. FILE *fp;
  398. int *first_image;
  399. {
  400.  LONG temp,i;
  401.  
  402.  for(i=0;i<6;i++) fgetc(fp);    /* read and toss GIF87a or GIF89? */
  403.  
  404.  gifscrn.width  = GIF_Get_Short(fp);
  405.  gifscrn.height = GIF_Get_Short(fp);
  406.  temp=fgetc(fp);
  407.  gifscrn.m       =  temp & 0x80;
  408.  gifscrn.cres    = (temp & 0x70) >> 4;
  409.  gifscrn.pixbits =  temp & 0x07;
  410.  gifscrn.bc  = fgetc(fp);
  411.  temp=fgetc(fp);
  412.  imagec=gif_ptwo[(1+gifscrn.pixbits)];
  413.  
  414.  if (verbose)
  415.   fprintf(stderr,"Screen: %ldx%ldx%ld m=%ld cres=%ld bkgnd=%ld pix=%ld\n",
  416.     gifscrn.width,gifscrn.height,imagec,gifscrn.m,gifscrn.cres,
  417.     gifscrn.bc,gifscrn.pixbits);
  418.  
  419.  if ( (imagec > x11_cmap_size) && (x11_cmap_flag == TRUE) )
  420.  {
  421.   fprintf(stderr,"ERROR: Image has %ld colors, display can handle %ld\n",
  422.                     imagec,x11_cmap_size);
  423.   TheEnd();
  424.  }
  425.  
  426.  i =0;
  427.  if (gifscrn.m)
  428.  {
  429.   if (x11_display_type == PSEUDO_COLOR_8BIT)
  430.   {
  431.    register int cmap_diff;
  432.    cmap_diff = 0;
  433.    for(i=0; i < imagec; i++)
  434.    {
  435.     register int d;
  436.     d = fgetc(fp); if (d != gifcolor[i].cmap.red) cmap_diff = 1;
  437.     gifcolor[i].cmap.red   = d;
  438.     d = fgetc(fp); if (d != gifcolor[i].cmap.green) cmap_diff = 1;
  439.     gifcolor[i].cmap.green = d;
  440.     d = fgetc(fp); if (d != gifcolor[i].cmap.blue) cmap_diff = 1;
  441.     gifcolor[i].cmap.blue  = d;
  442.    } /* end of for i */
  443.  
  444.    /***  Setup ACTION for CMAP */
  445.    if ( *first_image || cmap_diff)
  446.    {
  447.     ACTION *act;
  448.     ColorReg *act_cmap;
  449.     CMAP_HDR *cmap_hdr;
  450.  
  451.     *first_image = 0;
  452.  
  453.     act = &action[action_cnt];
  454.     action_cnt++;
  455.     act->type = ACT_CMAP;
  456.     act->time = 0;
  457.  
  458.     cmap_hdr = (CMAP_HDR *)
  459.                 malloc( imagec * sizeof(ColorReg) + sizeof(CMAP_HDR));
  460.     if (cmap_hdr == 0) TheEnd1("GIF_Read_COLOR: malloc failed\n");
  461.     act->data = (char *)cmap_hdr;
  462.     act_cmap = (ColorReg *)cmap_hdr->data;
  463.     cmap_hdr->cmap_size = imagec;
  464.  
  465.     for(i=0;i<imagec;i++)
  466.     {
  467.      act_cmap[i].red   = gifcolor[i].cmap.red;
  468.      act_cmap[i].green = gifcolor[i].cmap.green;
  469.      act_cmap[i].blue  = gifcolor[i].cmap.blue;
  470.     }
  471.    } /* end of let's make an cmap action */
  472.   } /* end of Pseudo Color */
  473.   else 
  474.   if (x11_display_type == TRUE_COLOR_24BIT)
  475.   {
  476.    for(i=0; i < imagec; i++)
  477.    {
  478.     gifcolor[i].pixel  = (fgetc(fp) & 0xff);
  479.     gifcolor[i].pixel |= (fgetc(fp) & 0xff) <<  8;
  480.     gifcolor[i].pixel |= (fgetc(fp) & 0xff) << 16;
  481.    } /* end of for i */
  482.   } /* end of True Color */
  483.  } /* end of image color map */
  484. } /* end of function */
  485.  
  486. void GIF_Image_Header(fp,first_image)
  487. FILE *fp;
  488. int *first_image;
  489. {
  490.  LONG temp,tnum,i;
  491.  
  492.  gifimage.left   = GIF_Get_Short(fp);
  493.  gifimage.top    = GIF_Get_Short(fp);
  494.  gifimage.width  = GIF_Get_Short(fp);
  495.  gifimage.height = GIF_Get_Short(fp);
  496.  temp=fgetc(fp);
  497.  gifimage.m        = temp & 0x80;
  498.  gifimage.i        = temp & 0x40;
  499.  if (gifimage.i) lace_flag = TRUE;
  500.  else lace_flag = FALSE;
  501.  gifimage.pixbits  = temp & 0x07;
  502.  imagex=gifimage.width;
  503.  imagey=gifimage.height;
  504.  tnum=gif_ptwo[(1+gifimage.pixbits)];
  505.  if (verbose)
  506.   fprintf(stderr,"Image: %ldx%ldx%ld m=%ld i=%ld pix=%ld \n",
  507.     imagex,imagey,tnum,gifimage.m,gifimage.i,gifimage.pixbits,
  508.     gifimage.reserved );
  509.  
  510.  if (gifimage.m)
  511.  {
  512.   if (tnum != imagec)
  513.   {
  514.    fprintf(stderr,"ERROR: Image has different number of colors than Screen\n");
  515.    fprintf(stderr,"This currently isn't supported. Let me know if you need it to be.\n");
  516.    TheEnd();
  517.   }
  518.  
  519.   if (x11_display_type == PSEUDO_COLOR_8BIT)
  520.   {
  521.     register int cmap_diff;
  522.     cmap_diff = 0;
  523.  
  524.     /* Read in Image CMAP
  525.      */
  526.     for(i=0; i < imagec; i++)
  527.     {
  528.       register int d;
  529.       d = fgetc(fp); if (d != gifcolor[i].cmap.red) cmap_diff = 1;
  530.       gifcolor[i].cmap.red   = d;
  531.       d = fgetc(fp); if (d != gifcolor[i].cmap.green) cmap_diff = 1;
  532.       gifcolor[i].cmap.green = d;
  533.       d = fgetc(fp); if (d != gifcolor[i].cmap.blue) cmap_diff = 1;
  534.       gifcolor[i].cmap.blue  = d;
  535.     }
  536.  
  537.     /* Setup ACTION for CMAP  if 1st colormap or cmap is different from
  538.      * previous cmap.
  539.      */
  540.     if ( *first_image || cmap_diff)
  541.     {
  542.       ACTION *act;
  543.       ColorReg *act_cmap;
  544.       CMAP_HDR *cmap_hdr;
  545.  
  546.       *first_image = 0;
  547.       act = &action[action_cnt];
  548.       action_cnt++;
  549.       act->type = ACT_CMAP;
  550.       act->time = 0;
  551.       cmap_hdr = (CMAP_HDR *)
  552.         malloc( imagec * sizeof(ColorReg) + sizeof(CMAP_HDR));
  553.       if (cmap_hdr == 0) TheEnd1("GIF_Read_COLOR: malloc failed\n");
  554.       act->data = (char *)cmap_hdr;
  555.       act_cmap = (ColorReg *)cmap_hdr->data;
  556.       cmap_hdr->cmap_size = imagec;
  557.       for(i=0;i<imagec;i++)
  558.       {
  559.         act_cmap[i].red   = gifcolor[i].cmap.red;
  560.         act_cmap[i].green = gifcolor[i].cmap.green;
  561.         act_cmap[i].blue  = gifcolor[i].cmap.blue;
  562.       }
  563.     } /* end of let's make an cmap action */
  564.  
  565.   }
  566.   else
  567.   if (x11_display_type == TRUE_COLOR_24BIT)
  568.   {
  569.     for(i=0; i < imagec; i++)
  570.     {
  571.       gifcolor[i].pixel  = (fgetc(fp) & 0xff);
  572.       gifcolor[i].pixel |= (fgetc(fp) & 0xff) <<  8;
  573.       gifcolor[i].pixel |= (fgetc(fp) & 0xff) << 16;
  574.     } /* end of i */
  575.   } /* end of True Color */
  576.  
  577.  } /* end of Image has cmap */
  578. }
  579.  
  580.  
  581. /*
  582.  *
  583.  */
  584. LONG GIF_Get_Short(fp)
  585. FILE *fp;
  586. {
  587.  register LONG temp;
  588.  temp=fgetc(fp);
  589.  return(temp|( (fgetc(fp)) << 8 ));
  590. }
  591.  
  592. /*
  593.  *
  594.  */
  595. LONG Is_GIF_File(filename)
  596. char *filename;
  597. {
  598.  FILE *fp;
  599.  ULONG firstword;
  600.  
  601.  if ( (fp=fopen(filename,"r")) == 0)
  602.  { 
  603.   fprintf(stderr,"can't open %s\n",filename); 
  604.   TheEnd();
  605.  }
  606.  /* by reading bytes we can ignore big/little endian problems */
  607.  firstword  = (fgetc(fp) & 0xff) << 24;
  608.  firstword |= (fgetc(fp) & 0xff) << 16;
  609.  firstword |= (fgetc(fp) & 0xff) <<  8;
  610.  firstword |= (fgetc(fp) & 0xff);
  611.  
  612.  fclose(fp);
  613.  
  614.  if (firstword == 0x47494638) return(TRUE);
  615.  return(FALSE);
  616. }
  617.